const logger = require("./logger");
const { spawn } = require("child_process");
// Use pigpio for hardware PWM
const Gpio = require('pigpio').Gpio;

/**
 * 硬件PWM控制模块
 * 使用pigpio库实现真正的硬件PWM控制
 */
class HardwarePWM {
  constructor() {
    this.activePins = new Map(); // 存储活跃的PWM引脚
    this.isInitialized = false;
    this.pwmPins = {}; // 存储pigpio PWM对象
    this.init();
  }

  /**
   * 初始化硬件PWM模块
   */
  async init() {
    try {
      logger.info("🔧 初始化硬件PWM控制模块...");
      
      // 检查pigpio是否正确初始化
      // pigpio需要以root权限运行
      if (process.getuid() !== 0) {
        throw new Error('pigpio requires root privileges. Please run with sudo');
      }
      
      this.isInitialized = true;
      logger.info("✅ 硬件PWM模块初始化完成");
      
    } catch (error) {
      logger.error("❌ 硬件PWM模块初始化失败:", error.message);
      this.isInitialized = false;
    }
  }

  /**
   * 设置PWM引脚
   * @param {number} pin - GPIO引脚号
   * @param {number} value - PWM值 (-1到1)
   */
  async setPWM(pin, value) {
    try {
      pin = parseInt(pin);
      value = Number(value);
      
      logger.info(`🎯 设置硬件PWM: 引脚${pin}, 值${value}`);
      
      // 如果是第一次设置这个引脚，初始化为PWM模式
      if (!this.activePins.has(pin)) {
        // 创建PWM对象
        this.pwmPins[pin] = new Gpio(pin, {mode: Gpio.OUTPUT});
        logger.debug(`引脚${pin}已设置为PWM输出模式`);
        this.activePins.set(pin, { value: 0 });
      }
      
      // 停止之前的PWM
      await this.stopPWM(pin);
      
      // 启动新的PWM控制
      if (value !== 0) {
        await this.startHardwarePWM(pin, value);
      } else {
        // 设置为中性位置
        await this.setNeutralPosition(pin);
      }
      
      // 更新引脚状态
      this.activePins.get(pin).value = value;
    } catch (error) {
      logger.error(`设置PWM引脚${pin}失败:`, error.message);
    }
  }

  /**
   * 启动硬件PWM - 使用标准舵机控制信号
   * @param {number} pin - GPIO引脚号
   * @param {number} value - PWM值 (-1到1)
   */
  async startHardwarePWM(pin, value) {
    // 计算PWM占空比 (舵机标准: 1ms-2ms高电平，20ms周期)
    // value范围: -1到1映射到1.0ms到2.0ms
    let dutyCycleMs;
    if (value === 0) {
      dutyCycleMs = 1.5; // 中性位置
    } else {
      // 确保值在-1到1范围内
      value = Math.max(-1, Math.min(1, value));
      dutyCycleMs = 1.5 + (value * 0.5); // 范围: 1.0ms 到 2.0ms
    }
    
    // 限制范围确保安全
    dutyCycleMs = Math.max(1.0, Math.min(2.0, dutyCycleMs));
    
    logger.debug(`启动硬件PWM: 引脚${pin}, 高电平${dutyCycleMs}ms`);
    
    // 转换为pigpio的duty cycle值 (0-1000000)
    // pigpio使用1秒=1,000,000微秒的单位，所以需要转换
    const frequency = 50; // 50Hz标准舵机频率
    const dutyCycle = (dutyCycleMs / 20.0) * 1000000; // 20ms周期
    
    // 使用pigpio设置硬件PWM
    this.pwmPins[pin].hardwarePwmWrite(frequency, dutyCycle);
  }

  /**
   * 设置中性位置 - 发送几个中性PWM脉冲后停止
   * @param {number} pin - GPIO引脚号
   */
  async setNeutralPosition(pin) {
    logger.debug(`设置引脚${pin}为中性位置`);
    
    // 发送10个中性位置脉冲 (1.5ms高电平)
    for (let i = 0; i < 10; i++) {
      const dutyCycle = (1.5 / 20.0) * 1000000;
      this.pwmPins[pin].hardwarePwmWrite(50, dutyCycle);
      await this.sleep(20); // 等待一个周期
    }
    
    // 最后停止PWM
    await this.stopPWM(pin);
  }

  /**
   * 停止指定引脚的PWM
   * @param {number} pin - GPIO引脚号
   */
  async stopPWM(pin) {
    if (this.pwmPins[pin]) {
      // 停止PWM并设置为低电平
      this.pwmPins[pin].digitalWrite(0);
      logger.debug(`停止引脚${pin}的PWM`);
    }
  }

  /**
   * 停止所有PWM
   */
  async stopAllPWM() {
    logger.info("🛑 停止所有PWM信号");
    
    for (const [pin, pinData] of this.activePins) {
      await this.stopPWM(pin);
    }
    
    // 清理PWM对象
    for (const pin in this.pwmPins) {
      this.pwmPins[pin].disableOutput();
      delete this.pwmPins[pin];
    }
    
    this.activePins.clear();
  }

  /**
   * 睡眠函数
   * @param {number} ms - 毫秒数
   */
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 获取引脚状态
   * @param {number} pin - GPIO引脚号
   */
  getPinStatus(pin) {
    const pinData = this.activePins.get(parseInt(pin));
    return pinData ? pinData.value : 0;
  }

  /**
   * 获取所有引脚状态
   */
  getAllStatus() {
    const status = {};
    for (const [pin, pinData] of this.activePins) {
      status[pin] = pinData.value;
    }
    return status;
  }
}

// 创建全局实例
const hardwarePWM = new HardwarePWM();

// 进程退出时清理
process.on('exit', () => {
  hardwarePWM.stopAllPWM();
});

process.on('SIGINT', () => {
  hardwarePWM.stopAllPWM();
  process.exit(0);
});

process.on('SIGTERM', () => {
  hardwarePWM.stopAllPWM();
  process.exit(0);
});

module.exports = hardwarePWM;